#include "config.h"

#include <iostream>
#include <string>
#if CFG_HAVE_STD_RANGES
#include <ranges>
#endif

using namespace cfg;

// 示例程序 2：演示 View 的路径访问、下钻、类型安全读取。
//  - 包含 has/subobj/at/lookup/get 的用法。
static void
print_error(const ConfigError & e)
{
    std::cerr << "[" << static_cast<int>(e.code) << "] " << e.message << "\n";
}

int
main()
{
    Builder b;

    // 构建嵌套对象与数组
    b.set("app.name", std::string("demo"));
    b.set("app.version", std::string("1.0"));
    b.set("features[0]", std::string("alpha"));
    b.set("features[1]", std::string("beta"));

    auto frozen = b.freeze();
    if (!frozen)
    {
        std::cerr << "build failed: " << frozen.error().size() << " error(s)\n";
        for (const auto & e : frozen.error())
            print_error(e);
        return 1;
    }

    View root(*frozen);

    // 逐段下钻
    if (root.has("app"))
    {
        auto app_view = root.subobj("app");
        if (app_view)
        {
            auto name = app_view->lookup("name").and_then([](const View & v)
                                                          { return v.get<std::string>(); });
            auto ver = app_view->lookup("version").and_then([](const View & v)
                                                            { return v.get<std::string>(); });
            if (name && ver)
                std::cout << "App: " << *name << " v" << *ver << "\n";
        }
    }

    // 数组访问：迭代索引
    auto feats = root.lookup("features").and_then([](const View & v) { return v.array_view(); });
    if (!feats)
    {
        print_error(feats.error());
        return 1;
    }
    auto feats_node = root.lookup("features");
    if (!feats_node)
    {
        print_error(feats_node.error());
        return 1;
    }
    for (size_t i = 0; i < feats->size(); ++i)
    {
        auto item = feats_node->at(i).and_then([](const View & v) { return v.get<std::string>(); });
        if (item)
            std::cout << "feature[" << i << "]: " << *item << "\n";
    }

    // 路径一次性查询
    auto maybe_name =
        root.lookup("app.name").and_then([](const View & v) { return v.get<std::string>(); });
    if (maybe_name)
        std::cout << "quick path: app.name = " << *maybe_name << "\n";

    return 0;
}
